package com.firexxx.study.performancetest.scene;

import com.firexxx.study.performancetest.task.IFixedTimeConsumeTask;
import com.firexxx.study.performancetest.task.ITask;
import com.firexxx.study.performancetest.timeconsume.ConsumeTaskType;
import com.firexxx.study.performancetest.timeconsume.ConsumeTimeArg;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author fireXXX
 * @date 2020/12/5 19:26
 **/
public class FixedTimeScene<R extends IResult> {

    public R startAsync(String sceneName, int thread, int sample, Map<String, IFixedTimeConsumeTask> tasks, Class<R> returnType) throws InterruptedException, IllegalAccessException, InstantiationException {
        R result = returnType.newInstance();
        result.setName(sceneName);

        Map<String, List<Thread>> threads = new HashMap<>();
        tasks.forEach((k, v) -> {
            List<Thread> list = new ArrayList<>();
            for (int i = 0; i < thread; i++) {
                list.add(new Thread(v));
            }
            threads.put(k, list);
        });

        threads.forEach((k, v) -> v.forEach(Thread::start));

        if (!returnType.getName().equals(SingleResult.class.getName())) {
            tasks.forEach((k, v) -> {
                SingleResult singleResult = new SingleResult(k);
                result.getData().add(singleResult);
            });
        }

        for (int i = 0; i < sample; i++) {
            Thread.sleep(1000);

            System.out.println(i);

            if (!returnType.getName().equals(SingleResult.class.getName())) {
                result.getData().forEach(item -> {
                    SingleResult singleResult = (SingleResult) item;
                    long count = tasks.get(singleResult.getName()).getCount();
                    System.out.println(singleResult.getName() + " : " + count);
                    singleResult.getData().add(count);
                });
            } else {
                long count = tasks.values().iterator().next().getCount();
                result.getData().add(count);
                System.out.println(sceneName + " : " + count);
            }

            System.out.println();
        }

        tasks.forEach((k, v) -> {
            v.stop();
        });

        return result;
    }

    public R startSync(String sceneName, int thread, int sample, Map<String, IFixedTimeConsumeTask> tasks, Class<R> returnType) throws InterruptedException, IllegalAccessException, InstantiationException {
        R result = returnType.newInstance();
        result.setName(sceneName);

        if (!returnType.getName().equals(SingleResult.class.getName())) {
            for (Map.Entry<String, IFixedTimeConsumeTask> entry : tasks.entrySet()) {
                String itemName = entry.getKey();

                IFixedTimeConsumeTask task = entry.getValue();
                SingleResult singleResult = new SingleResult(itemName);
                runTask(itemName, thread, sample, task, singleResult);
                result.getData().add(singleResult);
            }
        } else {
            IFixedTimeConsumeTask task = tasks.values().iterator().next();
            SingleResult singleResult = (SingleResult) result;
            runTask(sceneName, thread, sample, task, singleResult);
        }

        return result;
    }

    private void runTask(String sceneName, int thread, int sample, IFixedTimeConsumeTask task, SingleResult singleResult) throws InterruptedException {
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < thread; i++) {
            threads.add(new Thread(task));
        }

        threads.forEach(Thread::start);

        for (int i = 0; i < sample; i++) {
            Thread.sleep(1000);

            System.out.println(i);

            long count = task.getCount();
            singleResult.getData().add(count);
            System.out.println(sceneName + "-" + thread + "-" + task.getTimeConsume().getTime() + " : " + count);

            System.out.println();
        }

        task.stop();
    }

}